var _ = require('lodash'),
    Q = require('q'),
    BaseFun = require('../../../Base/server/controllers/Function'),
    BaseEnum = require('../../../Base/server/controllers/Enum'),
    QCEnum = require('../../../QC/server/controllers/Enum.server.controller'),
    Transaction = require('../../../Base/server/controllers/Transaction'),
    ProduceWorkEnum = require('../../../ProduceWork/server/controllers/Enum.server.controller.js'),
    barcodeMasterController = require('../../../Barcode/server/controllers/BarcodeMaster.server.controller'),
    terminalController = require('../../../CBO/server/controllers/Terminal.server.controller'),
    stationWorkController = require('../../../Initialize/server/controllers/StationWork.server.controller'),
    operationController = require('../../../CBO/server/controllers/Operation.server.controller'),
    bizRecordController = require('../../../Barcode/server/controllers/BizRecord.server.controller'),
    qcStandardController = require('../../../QC/server/controllers/QCStandard.server.controller'),
    qcRecordController = require('../../../QC/server/controllers/QCRecord.server.controller'),
    workLocationController = require('../../../CBO/server/controllers/WorkLocation.server.controller'),
    wareHouseController = require('../../../CBO/server/controllers/WareHouse.server.controller'),
    rcvRecordController = require('../../../ProduceWork/server/controllers/RcvRecord.server.controller');

exports.getWrapperInfo = function (req, res) {
    var parameter = req.body.Parameter,
        barcode = parameter.Barcode,
        terminalUniqueID = parameter.TerminalUniqueID,
        HDWork = parameter.HDWork;//jiadx根据业务需要,获取壳子的作业(独立称重)

    var wrapperInfo = {
        basicInfo: {}
    }, barcodeMaster;
    queryBarcodeMaster(barcode).then(function (record) {
        _.merge(wrapperInfo.basicInfo, {
            MOCode: record.MOCode,
            ItemMasterCode: record.ItemMasterCode,
            ItemMasterName: record.ItemMasterName,
            MOLotNumber: record.MOLotNumber,
            Users: record.Users,
            Work: record.Work ? record.Work._id : '',
            WorkName: record.Work ? record.Work.Name : '',
            WorkLocation: record.WorkLocation ? record.WorkLocation : '',
            WorkLocationName: record.WorkLocationName ? record.WorkLocationName : '',
            DescSeg1: record.DescSeg1,  // 尺寸
            DescSeg2: record.DescSeg2   // 外观
        });
        if (record.ItemMaster) {
            _.merge(wrapperInfo.basicInfo, {
                ItemMaster: record.ItemMaster._id,
                Specification: record.ItemMaster.Specification
            });
        }
        barcodeMaster = record;
        return queryWork(terminalUniqueID);
    }).then(function (work) {
        return queryOperation(wrapperInfo.basicInfo.ItemMaster, work.Work);
    }).then(function (operation) {
        var bindContext = {User: wrapperInfo.basicInfo.Users[0]};
        _.merge(bindContext, wrapperInfo.basicInfo);
        return barcodeMasterController.streamValidation(barcodeMaster, operation, bindContext, { containModify: true });
    }).then(function (processException) {
        if (processException) {
            return Q.nfcall(Transaction.BatchSaveByTran, [processException]);
        } else {
            return Q.resolve();
        }
    }).then(function () {
        return queryQCStandard(wrapperInfo.basicInfo.ItemMaster, HDWork._id, barcodeMaster.DescSeg3);
    }).then(function (qcStandard) {
        wrapperInfo.qcStandard = qcStandard;
        res.json({
            Data: wrapperInfo,
            Error: null
        });
    }).catch(function (err) {
        res.json({
            Data: null,
            Error: err
        });
    })
        .done();
};

exports.setWrapperMeasure = function (req, res) {
    var parameter = req.body.Parameter,
        barcode = parameter.Barcode,
        work = parameter.Work,
        terminalUniqueID = parameter.TerminalUniqueID,
        users = parameter.Users,
        qcRecords = parameter.QCRecords;

    var relQCStatus = 0;
    for (var i = 0; i < qcRecords.length; i++) {
        if (!qcRecords[i].ValueLowerLimit || !qcRecords[i].ValueUpperLimit || qcRecords[i].NormValue < qcRecords[i].ValueLowerLimit || qcRecords[i].NormValue > qcRecords[i].ValueUpperLimit) {
            relQCStatus = 6;
            break;
        } else {
            relQCStatus = 0;
        }
    }

    var baseInfo = {
        Work: work,
        WorkName: parameter.WorkName,
        Users: users,
        BusinessStatus: 1,
        QCStatus: relQCStatus,
        QCType: 0
    }, transactions = [], isModify = false, bizRecordId, barcodeMaster, operation;

    queryHardwareInfo(terminalUniqueID).then(function (terminalInfo) {
        _.merge(baseInfo, terminalInfo);
        return queryBarcodeMaster(barcode);
    }).then(function (record) {
        barcodeMaster = record;
        return queryOperation(record.ItemMaster._id, work);
    }).then(function (op) {
        operation = op;
        _.merge(baseInfo, { Operation: op._id, OperationName: op.Name });

        var bizRecord = {
            QCUser: parameter.Users[0] ? parameter.Users[0] : null,
            QCDateTime: Date.now(),
            BarcodeMaster: barcodeMaster._id
        };
        if (barcodeMaster.BizRecord &&
            (barcodeMaster.BizRecord.Work.toString() === work) &&
            (barcodeMaster.BizRecord.Terminal.toString() === baseInfo.Terminal.toString()) &&
            barcodeMaster.QCType === QCEnum.QCType.FullReview.Value
        ) {
            bizRecordId = barcodeMaster.BizRecord._id;
            bizRecord.RowStatus = BaseEnum.RowStatus.Modify.Value;
            bizRecord.SysVersion = barcodeMaster.BizRecord.SysVersion;
            bizRecord.ModifyBy = bizRecord.QCUser;
            isModify = true;
        } else {
            bizRecordId = BaseFun.getObjectId();
            bizRecord.RowStatus = BaseEnum.RowStatus.Insert.Value;
            bizRecord.CreatedBy = bizRecord.QCUser;
            isModify = false;
        }

        _.merge(bizRecord, baseInfo);
        bizRecord._id = bizRecordId;
        transactions.push({ EntityName: 'BizRecord', Records: [bizRecord] });

        var updateBarcodeMaster = {
            _id: barcodeMaster._id,
            RowStatus: BaseEnum.RowStatus.Modify.Value,
            ModifyBy: bizRecord.QCUser,
            SysVersion: barcodeMaster.SysVersion,
            BizRecord: bizRecordId,
            QCReworkOperation: null
        };
        _.merge(updateBarcodeMaster, baseInfo);
        transactions.push({ EntityName: 'BarcodeMaster', Records: [updateBarcodeMaster] });

        if (isModify) {
            return Q.nfcall(qcRecordController.findAllQCRecords, bizRecordId);
        } else {
            return Q.resolve();
        }
    }).then(function (records) {
        if (records && records.length > 0) {
            var deleteRecords = [];
            _.forEach(records, function (qcRecord) {
                deleteRecords.push({
                    _id: qcRecord._id,
                    RowStatus: BaseEnum.RowStatus.Delete.Value
                });
            });
            transactions.push({ EntityName: 'QCRecord', Records: deleteRecords });
        }
        var userId = users[0];
        _.forEach(qcRecords, function (qcRecord) {
            qcRecord.BizRecord = bizRecordId;
            qcRecord.RowStatus = BaseEnum.RowStatus.Insert.Value;
            qcRecord.CreatedBy = userId;
        });
        transactions.push({ EntityName: 'QCRecord', Records: qcRecords });

        return addStockQty(barcodeMaster, baseInfo, operation, isModify);
    }).then(function (tran) {
        if (tran) {
            transactions.push(tran);
        }
        return Q.nfcall(Transaction.BatchSaveByTran, transactions);
    }).then(function () {
        res.json({
            Data: true,
            Error: null
        });
    }).catch(function (err) {
        res.json({
            Data: null,
            Error: err
        });
    }).done();
};

exports.setWrapperTagPrint = function (req, res) {
    var parameter = req.body.Parameter,
        barcode = parameter.Barcode,
        work = parameter.Work,
        terminalUniqueID = parameter.TerminalUniqueID,
        users = parameter.Users;

    var bizRecord = {
        Work: work,
        WorkName: parameter.WorkName,
        Users: users,
        BusinessStatus: 1,
        QCType: 0,
        QCUser: parameter.Users[0] ? parameter.Users[0] : '',
        QCDateTime: Date.now()
    };
    queryTerminalInfo(terminalUniqueID).then(function (terminalInfo) {
        _.merge(bizRecord, terminalInfo);
        return queryBusiness(barcode, work, parameter.realWorkLocation, parameter.realWorkLocationName);
    }).then(function (result) {
        var bizRecordId = null;
        if (result.BizRecord &&
            (result.BizRecord.Work.toString() === work) &&
            result.QCType === QCEnum.QCType.FullReview.Value
        ) {
            bizRecordId = result.BizRecord._id;
        }
        delete result.BizRecord;
        delete result.QCType;
        _.merge(bizRecord, result);
        return updateBizData(barcode, bizRecord, bizRecordId);
    }).then(function () {
        res.json({
            Data: true,
            Error: null
        });
    }).catch(function (err) {
        res.json({
            Data: null,
            Error: err
        });
    }).done();
};

function queryBarcodeMaster(barcode) {
    var deferred = Q.defer();

    barcodeMasterController.findBarcodeMaster(barcode, function (err, barcodeMaster) {
        if (err) {
            deferred.reject(err);
            return;
        }
        if (!barcodeMaster || barcodeMaster.BarcodeType != 0) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询物料错误';
            newErr.message = '无法识别的芯片，请重新扫描！';
            deferred.reject(newErr);
            return;
        }
        deferred.resolve(barcodeMaster);
    });

    return deferred.promise;
}

function queryWork(terminalUniqueID) {
    var deferred = Q.defer();

    stationWorkController.getStationWorksByTerminalUniqueID(terminalUniqueID, function (err, stationWorkRecords) {
        if (err) {
            deferred.reject(err);
            return;
        }
        if (stationWorkRecords.length > 0) {
            deferred.resolve({
                Work: stationWorkRecords[0].Work._id,
                WorkName: stationWorkRecords[0].Work.Name
            });
        } else {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询作业错误';
            newErr.message = '没有找到作业，请重新扫描！';
            deferred.reject(newErr);
        }
    });

    return deferred.promise;
}

function queryOperation(itemMaster, work) {
    var deferred = Q.defer();

    operationController.findByItemMasterAndWork(itemMaster, work, function (err, result) {
        if (err) {
            deferred.reject(err);
            return;
        }
        if (!result) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '非法数据';
            newErr.message = '没有找到对应的工序';
            deferred.reject(newErr);
            return;
        }
        deferred.resolve(result);
    });

    return deferred.promise;
}

function queryQCStandard(ItemMasterId, Work, isNet) {
    var deferred = Q.defer();

    qcStandardController.findQCStandard(ItemMasterId, Work, isNet, function (err, qcStandards) {
        if (err) {
            deferred.reject(err);
            return;
        }
        if (!qcStandards) {
            deferred.resolve([]);
            return;
        }
        var result = [];
        _.forEach(qcStandards, function (qcStandard) {
            result.push({
                QCStandard: qcStandard._id,
                QCNorm: qcStandard.QCNorm._id,
                QCCode: qcStandard.QCNorm.Code,
                QCNormName: qcStandard.QCNorm.Name,
                QCNormUnit: qcStandard.QCNorm.Unit,
                StandardValue: qcStandard.StandardValue,
                ValueUpperLimit: qcStandard.ValueUpperLimit,
                ValueLowerLimit: qcStandard.ValueLowerLimit
            });
        });
        deferred.resolve(result);
    });

    return deferred.promise;
}

function queryHardwareInfo(terminalUniqueID) {
    var deferred = Q.defer();

    terminalController.findByUniqueID(terminalUniqueID, function (err, terminalRecord) {
        if (err) {
            deferred.reject(err);
            return;
        }
        if (terminalRecord == null) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询终端错误';
            newErr.message = '请检查查询参数！';
            deferred.reject(newErr);
            return;
        }
        var hardwareInfo = {
            Terminal: terminalRecord._id,
            TerminalName: terminalRecord.Name
        };
        stationWorkController.getStationWorksByTerminalID(terminalRecord._id, function (err, stationWorkRecords) {
            if (err) {
                deferred.reject(err);
                return;
            }
            if (stationWorkRecords.length > 0) {
                hardwareInfo.WorkLocation = stationWorkRecords[0].WorkLocation._id;
                hardwareInfo.WorkLocationName = stationWorkRecords[0].WorkLocation.Name;
                hardwareInfo.WorkLocationShared = stationWorkRecords[0].WorkLocation.IsShared;
                hardwareInfo.Work = stationWorkRecords[0].Work._id;
                hardwareInfo.WorkName = stationWorkRecords[0].Work.Name;
            }
            deferred.resolve(hardwareInfo);
        });
    });

    return deferred.promise;
}

function queryTerminalInfo(terminalUniqueID) {
    var deferred = Q.defer();

    terminalController.findByUniqueID(terminalUniqueID, function (err, terminalRecord) {
        if (err) {
            deferred.reject(err);
            return;
        }
        if (terminalRecord == null) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询终端错误';
            newErr.message = '请检查查询参数！';
            deferred.reject(newErr);
            return;
        }
        deferred.resolve({
            Terminal: terminalRecord._id,
            TerminalName: terminalRecord.Name
        });
    });

    return deferred.promise;
}

function queryBusiness(barcode, work, realWorkLocation, realWorkLocationName) {
    var deferred = Q.defer();

    barcodeMasterController.findBarcodeMaster(barcode, function (err, record) {
        if (err) {
            deferred.reject(err);
            return;
        }
        if (!record.ItemMaster) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '数据错误';
            newErr.message = '主档没有绑定物料';
            deferred.reject(newErr);
            return;
        }
        operationController.findByItemMasterAndWork(record.ItemMaster._id, work, function (err, result) {
            if (err) {
                deferred.reject(err);
                return;
            }
            var data = {
                BarcodeMaster: record._id,
                BizRecord: record.BizRecord,
                QCType: record.QCType,
                WorkLocation: realWorkLocation,
                WorkLocationName: realWorkLocationName
            };
            if (result) {
                _.merge(data, {
                    Operation: result._id,
                    OperationName: result.Name
                });
            }
            deferred.resolve(data);
        });
    });

    return deferred.promise;
}

function updateBizData(barcode, bizRecord, bizRecordId, qcRecords) {
    var deferred = Q.defer();

    writeBizData(bizRecord, bizRecordId, qcRecords).then(function (BizRecord) {
        var temp = _.clone(bizRecord);
        delete temp._id;
        delete temp.BarcodeMaster;
        temp.BizRecord = BizRecord._id;
        temp.QCType = QCEnum.QCType.FullReview.Value;
        temp.QCReworkOperation = null;
        barcodeMasterController.updateByValue(barcode, temp, function (err, result) {
            if (err) {
                deferred.reject(err);
                return;
            }
            deferred.resolve(BizRecord);
        });
    }, function (err) {
        deferred.reject(err);
    });

    return deferred.promise;
}

function writeBizData(bizRecord, bizRecordId, qcRecords) {
    var deferred = Q.defer();

    if (bizRecordId) {
        bizRecordController.updateBizRecordByValue(bizRecordId, bizRecord, function (err) {
            if (err) {
                deferred.reject(err);
                return;
            }
            var deleteBatches = [];
            _.forEach(qcRecords, function (qcRecord) {
                deleteBatches.push(qcRecordController.deleteByStandarsNorm(qcRecord.QCStandard, qcRecord.QCNorm, bizRecordId));
            });
            Q.all(deleteBatches).then(function () {
                bizRecord._id = bizRecordId;
                deferred.resolve(bizRecord);
            }, function (err) {
                deferred.reject(err);
            });
        });
    } else {
        bizRecordController.insert(bizRecord, function (err, record) {
            if (err) {
                deferred.reject(err);
                return;
            }
            deferred.resolve(record);
        });
    }

    return deferred.promise;
}

function writeQCRecords(qcRecords) {
    var deferred = Q.defer();

    Transaction.BatchSaveByTran([
            {EntityName: 'QCRecord', Records: qcRecords}
        ],
        function (err, result) {
            if (err) {
                deferred.reject(err);
                return;
            }
            deferred.resolve(result);
        }
    );

    return deferred.promise;
}

function addStockQty(barcodeMaster, bizRecord, operation, isModify) {
    var deferred = Q.defer();

    var needStock = operation && operation.IsStoragePoint 
        && (bizRecord.QCStatus === QCEnum.QCStatus.Qualified.Value
        || bizRecord.QCStatus === QCEnum.QCStatus.Concession.Value);
    if (!needStock && !isModify) {
        deferred.resolve();
    } else {
        rcvRecordController.queryRcvRecordsByBarcodeMaster(barcodeMaster._id, function (err, record) {
            if (err) {
                deferred.reject(err);
                return;
            }
            if (needStock) {
                if (record) {
                    deferred.resolve();
                    return;
                }
                workLocationController.findById(
                    bizRecord.WorkLocation, {Department: 1}, {path: 'Department', select: 'Name'}
                ).then(function (workLocationRecord) {
                    if (!workLocationRecord) {
                        var newErr = new Error();
                        newErr.leval = 9;
                        newErr.title = '查询工位错误';
                        newErr.message = '没有找到对应工位';
                        deferred.reject(newErr);
                        return;
                    }
                    return wareHouseController.findByDepartmentDeep(workLocationRecord.Department._id);
                }).then(function (wareHouse) {
                    if (!wareHouse) {
                        var newErr = new Error();
                        newErr.leval = 9;
                        newErr.title = '查询仓库';
                        newErr.message = '没有找到对应的仓库';
                        deferred.reject(newErr);
                    }
                    deferred.resolve({
                        EntityName: 'RcvRecord',
                        Records: [{
                            RowStatus: BaseEnum.RowStatus.Insert.Value,
                            CreatedBy: (bizRecord.Users && bizRecord.Users.length > 0) ? bizRecord.Users[0] : null,
                            RcvBusinessType: ProduceWorkEnum.RcvBusinessType.WareHouse.Value,
                            RcvQty: 1,
                            BarcodeMaster: barcodeMaster._id,
                            Barcode: barcodeMaster.Barcode,
                            ItemMaster: barcodeMaster.ItemMaster ? barcodeMaster.ItemMaster._id : '',
                            DescSeg1: barcodeMaster.DescSeg1,
                            DescSeg2: barcodeMaster.DescSeg2,
                            BusinessDocID: barcodeMaster.MO ? barcodeMaster.MO._id : '',
                            RcvUser: (bizRecord.Users && bizRecord.Users.length > 0) ? bizRecord.Users[0] : null,
                            RcvOperation: operation._id,
                            BizRecord: bizRecord.BizRecord,
                            WareHouse: wareHouse._id,
                            RcvDateTime: new Date()
                        }]
                    });
                });
                return;
            }
            if (record) {
                deferred.resolve({
                    EntityName: 'RcvRecord',
                    Records: [{
                        RowStatus: BaseEnum.RowStatus.Delete.Value,
                        _id: record._id
                    }]
                });
            } else {
                deferred.resolve();
            }
        });
    }

    return deferred.promise;
}
